package com.yj.springbootmiaosha.service;

import com.yj.springbootmiaosha.entity.Order;
import com.yj.springbootmiaosha.entity.OrderItem;
import com.yj.springbootmiaosha.entity.Product;
import com.yj.springbootmiaosha.mapper.OrderDao;
import com.yj.springbootmiaosha.mapper.OrderItemDao;
import com.yj.springbootmiaosha.mapper.ProductDao;
import org.springframework.stereotype.Service;
import org.springframework.transaction.PlatformTransactionManager;
import org.springframework.transaction.TransactionDefinition;
import org.springframework.transaction.TransactionStatus;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import java.math.BigDecimal;
import java.util.Date;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;

@Service
public class OrderService {

    @Resource
    private OrderDao orderDao;

    @Resource
    private OrderItemDao orderItemDao;

    @Resource
    private ProductDao productDao;


    // 模拟购买商品的id
    private int purchaseProductId = 100;

    // 购买商品的数量
    private int purchaseProductNum = 1;


    // 手动的事务控制
    @Resource
    private PlatformTransactionManager platformTransactionManager;

    @Resource
    private TransactionDefinition transactionDefinition;

    static Lock lock = new ReentrantLock();


//    @Transactional(rollbackFor = Exception.class)
//    public synchronized Integer createOrder(){  同步方法
    public Integer createOrder(){
        Product product = null;

        try {
            lock.lock();
       // synchronized (this) { //使用同步代码块
            // 获取事务
            TransactionStatus transactionStatus = platformTransactionManager.getTransaction(transactionDefinition);

            //1，校验商品
            product = productDao.selectByPrimaryKey(purchaseProductId);
            if (null == product) {
                // 回滚事务
                platformTransactionManager.rollback(transactionStatus);
                throw new RuntimeException("购买商品：" + purchaseProductId + "不存在！");
            }
            //2. 校验库存; 购买的数量 大于 库存数 则报错
            Integer dbCount = product.getCount();

            if (purchaseProductNum > dbCount) {
                platformTransactionManager.rollback(transactionStatus);
                throw new RuntimeException("商品：" + purchaseProductId + "仅剩：" + dbCount + "件；无法完成购买！");
            }

            //3. 计算剩余库存
            Integer leftCount = dbCount - purchaseProductNum;
            //4. 更新库存
            // todo 这里会出现超卖问题！
//        product.setCount(leftCount);
//        product.setUpdateTime(new Date());
//        product.setUpdateUser("yj");
//        productDao.updateByPrimaryKey(product);

            // todo 将超卖问题控制在数据库,但是会出现库存为复数的情况
            productDao.updateCount(purchaseProductNum, "yj", new Date(), purchaseProductId);

            // 提交事务
            platformTransactionManager.commit(transactionStatus);
            // todo 最终解决方案：要将 库存校验和扣减库存 行成一个原子操作
        }finally {
            lock.unlock();
        }


        TransactionStatus transactionStatus = platformTransactionManager.getTransaction(transactionDefinition);

        //5. 创建订单
        Order order = new Order();
        order.setCreateTime(new Date());
        order.setCreateUser("yj");
        order.setOrderAmount(product.getPrice().multiply(new BigDecimal(purchaseProductNum+"")));
        order.setOrderStatus(1); //待支付
        order.setReceiverName("yj");
        order.setReceiverMobile("123123");
        orderDao.insert(order);

        //6. 创建订单明细
        OrderItem orderItem = new OrderItem();
        orderItem.setOrderId(order.getId());
        orderItem.setProductId(product.getId());
        orderItem.setCreateTime(new Date());
        orderItem.setCreateUser("yj");
        orderItem.setPurchaseNum(purchaseProductNum);
        orderItem.setProductId(purchaseProductId);
        orderItem.setUpdateTime(new Date());
        orderItem.setUpdateUser("yj");
        orderItem.setPurchasePrice(product.getPrice());
        orderItemDao.insert(orderItem);
        // 提交事务
        platformTransactionManager.commit(transactionStatus);

        //返回订单id
        return order.getId();
    }
}
